package com.supermap.desktop.mapview.layer.propertymodel;

import java.beans.PropertyChangeEvent;
import java.util.HashMap;
import java.util.Set;

import javax.swing.event.EventListenerList;

import com.supermap.desktop.Application;
import com.supermap.desktop.mapview.layer.propertycontrols.ChangedListener;
import com.supermap.desktop.utilties.StringUtilties;
import com.supermap.mapping.Layer;
import com.supermap.mapping.Map;

/**
 * 派生类需自行写代码实现属性可用状态的检测以及可用状态改变的事件发送过程
 * 
 * @author highsad
 *
 */
public abstract class LayerPropertyModel implements Cloneable {

	private Layer[] layers;
	private Map map;
	private EventListenerList listenerList = new EventListenerList();
	protected HashMap<String, Boolean> propertyEnabled = new HashMap<String, Boolean>();

	public LayerPropertyModel() {

	}

	public LayerPropertyModel(Layer[] layers, Map map) {
		this.layers = layers;
		this.map = map;
	}

	public Layer[] getLayers() {
		return layers;
	}

	public Map getMap() {
		return map;
	}

	public final void refresh() {
		if (this.map != null) {
			this.map.refresh();
		}
	}

	public Set<String> getPropertyNames() {
		return this.propertyEnabled.keySet();
	}

	public final boolean isPropertyEnabled(String propertyName) {
		return this.propertyEnabled.get(propertyName);
	}

	public final boolean apply() {
		boolean result = false;

		try {
			if (this.layers != null && this.layers.length > 0) {
				for (Layer layer : layers) {
					apply(layer);
				}
			}
			result = true;
		} catch (Exception e) {
			Application.getActiveApplication().getOutput().output(e);
		}
		return result;
	}

	@Override
	public final LayerPropertyModel clone() {
		LayerPropertyModel result = null;

		try {
			result = this.getClass().newInstance();
			result.layers = this.getLayers();
			result.map = this.getMap();
			result.setProperties(this);
			result.propertyEnabled = (HashMap<String, Boolean>) this.propertyEnabled.clone();
		} catch (Exception e) {
			Application.getActiveApplication().getOutput().output(e);
		}
		return result;
	}

	public final void addPropertyEnabledChangeListener(PropertyEnabledChangeListener listener) {
		this.listenerList.add(PropertyEnabledChangeListener.class, listener);
	}

	public final void removePropertyEnabledChangeListener(PropertyEnabledChangeListener listener) {
		this.listenerList.remove(PropertyEnabledChangeListener.class, listener);
	}

	/**
	 * 使用指定 model 的数据设置自己的属性 子类必须重写这个方法
	 * 
	 * @param model
	 */
	public abstract void setProperties(LayerPropertyModel model);

	/**
	 * 子类必须重写这个方法
	 * 
	 * @param model
	 * @return
	 */
	public boolean equals(LayerPropertyModel model) {
		return this.layers == model.getLayers() && this.map == model.getMap();
	}

	/**
	 * 在指定的图层上应用属性设置 子类必须重写这个方法
	 * 
	 * @param layer
	 */
	protected abstract void apply(Layer layer);

	protected final void checkPropertyEnabled(String propertyName, boolean enabled) throws InvalidPropertyException {
		if (StringUtilties.isNullOrEmpty(propertyName)) {
			throw new InvalidPropertyException();
		}

		if (!this.propertyEnabled.containsKey(propertyName)) {
			throw new InvalidPropertyException("property is not exist.");
		}

		if (this.propertyEnabled.get(propertyName) != enabled) {
			this.propertyEnabled.put(propertyName, enabled);
			firePropertyEnabledChange(new PropertyEnabledChangeEvent(this, propertyName, enabled));
		}
	}

	protected void firePropertyEnabledChange(PropertyEnabledChangeEvent e) {
		Object[] listeners = listenerList.getListenerList();

		for (int i = listeners.length - 2; i >= 0; i -= 2) {
			if (listeners[i] == PropertyEnabledChangeListener.class) {
				((PropertyEnabledChangeListener) listeners[i + 1]).propertyEnabeldChange(e);
			}
		}
	}
}
